/************************************************************************
*    File Name:  rt771_6b_packer.v
*     Revision:  V1.0
* Release Date:  2015/06/18
*        Model:
* Dependencies:
*  Description:  (For 1H503)
*                iSP  Packer 6 bits to 8 bits (rdclk: 14T, rdfclk: 8T clock latency)
*
*      Company:  AUO
*     Engineer:  Jie Ho
*  Create Date:  2015/06/16
*
* Rev  Author        Date        Changes
* ---  ------------  ----------  ---------------------------------------
* 1.0  Jie Ho        2015/06/18  Initial release
************************************************************************/

`timescale 1ns/10ps

module rt771_6b_packer(
// Input 
reset_n,
dclk,

isp_en,
port_num,
opbit,
final_pasel,

in_de,
in_r,
in_g,
in_b,
in_srart,
in_cycle_cnt,
in_port_define,


// Output
o_fifo_din,
o_fifo_wen,
o_fifo_waddr,
o_fifo_ren,
o_fifo_raddr

);


// Input 
input       reset_n;        
input       dclk;   

input       isp_en;
input [2:0] port_num;     
input [1:0] opbit;
input       final_pasel;

input       in_de;
input [9:0] in_r;
input [9:0] in_g;
input [9:0] in_b;
input       in_srart;
input [2:0] in_cycle_cnt;
input [4:0] in_port_define;   //port0~port15


// Output
output [29:0] o_fifo_din;
output        o_fifo_wen;
output        o_fifo_ren;
output [4:0]  o_fifo_waddr;
output [4:0]  o_fifo_raddr;







///////////////////////////////////////////////
//                                           //
//              flag process                 //
//                                           //
///////////////////////////////////////////////

//port number settihg flag
wire port_num_4 = (port_num == 3'd0) ? 1'd1 : 1'd0;      
wire port_num_6 = (port_num == 3'd1) ? 1'd1 : 1'd0;
wire port_num_8 = (port_num == 3'd2) ? 1'd1 : 1'd0;
wire port_num_12 = (port_num == 3'd3) ? 1'd1 : 1'd0;
wire port_num_16 = (port_num == 3'd4) ? 1'd1 : 1'd0;

wire port_num_4n = port_num_4 | port_num_8 | port_num_12 | port_num_16;



//packer number setting flag
wire port_1 = (in_port_define == 5'd1) ? 1'd1 : 1'd0;
wire port_2 = (in_port_define == 5'd2) ? 1'd1 : 1'd0;
wire port_3 = (in_port_define == 5'd3) ? 1'd1 : 1'd0;
wire port_4 = (in_port_define == 5'd4) ? 1'd1 : 1'd0;
wire port_5 = (in_port_define == 5'd5) ? 1'd1 : 1'd0;
wire port_6 = (in_port_define == 5'd6) ? 1'd1 : 1'd0;
wire port_7 = (in_port_define == 5'd7) ? 1'd1 : 1'd0;
wire port_8 = (in_port_define == 5'd8) ? 1'd1 : 1'd0;
wire port_9 = (in_port_define == 5'd9) ? 1'd1 : 1'd0;
wire port_10 = (in_port_define == 5'd10) ? 1'd1 : 1'd0;
wire port_11 = (in_port_define == 5'd11) ? 1'd1 : 1'd0;
wire port_12 = (in_port_define == 5'd12) ? 1'd1 : 1'd0;
wire port_13 = (in_port_define == 5'd13) ? 1'd1 : 1'd0;
wire port_14 = (in_port_define == 5'd14) ? 1'd1 : 1'd0;
wire port_15 = (in_port_define == 5'd15) ? 1'd1 : 1'd0;
wire port_16 = (in_port_define == 5'd16) ? 1'd1 : 1'd0;

wire port_1256 = port_1 | port_2 | port_5 | port_6;
wire port34 = port_3 | port_4;




//de delay
reg de_d1, de_d2, de_d3, de_d4, de_d5, de_d6;
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n) 
 begin
 de_d1 <= 1'd0;
 de_d2 <= 1'd0;
 de_d3 <= 1'd0;
 de_d4 <= 1'd0;
 de_d5 <= 1'd0;
 de_d6 <= 1'd0; end
 else begin
      de_d1 <= in_de;
      de_d2 <= de_d1;
      de_d3 <= de_d2;
      de_d4 <= de_d3;
      de_d5 <= de_d4;
      de_d6 <= de_d5;
 end
end





//date delay for 8/10 bit data output
wire [29:0] in_data = {in_r, in_g, in_b}
reg data_d1, data_d2, data_d3, data_d4, data_d5, data_d6, data_d7, data_d8, data_d9;
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n) 
 begin
 data_d1 <= 1'd0;
 data_d2 <= 1'd0;
 data_d3 <= 1'd0;
 data_d4 <= 1'd0;
 data_d5 <= 1'd0;
 data_d6 <= 1'd0; 
 data_d7 <= 1'd0;
 data_d8 <= 1'd0;
 data_d9 <= 1'd0;  end
 else begin
      data_d1 <= in_data;
      data_d2 <= data_d1;
      data_d3 <= data_d2;
      data_d4 <= data_d3;
      data_d5 <= data_d4;
      data_d6 <= data_d5;
	  data_d7 <= data_d6;
	  data_d8 <= data_d7;
	  data_d9 <= data_d8;
 end
end










///////////////////////////////////////////////
//                                           //
//      shift reg write in package data      //
//                                           //
///////////////////////////////////////////////

// for wr_cycle_cnt add flag
wire cycle_0 = (in_cycle_cnt == 3'd0) ? 1'd1: 1'd0;
wire cycle_1 = (in_cycle_cnt == 3'd1) ? 1'd1: 1'd0;
wire cycle_2 = (in_cycle_cnt == 3'd2) ? 1'd1: 1'd0;
wire cycle_3 = (in_cycle_cnt == 3'd3) ? 1'd1: 1'd0;
wire cycle_4 = (in_cycle_cnt == 3'd4) ? 1'd1: 1'd0;
wire cycle_5 = (in_cycle_cnt == 3'd5) ? 1'd1: 1'd0;




// wr_cycle_cnt

reg [2:0] wr_cycle_cnt_6p_1256;                 //wr_cycle_cnt for 1256 port of 6port case
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
 wr_cycle_cnt_6p_1256 <= 3'd0;
 else begin
   if (in_srart)
   wr_cycle_cnt_6p_1256 <= 3'd0;
   else if (port_num_6 & (cycle_0 | cycle_2 | cycle_3 | cycle_5))
        wr_cycle_cnt_6p_1256 <= wr_cycle_cnt_6p_1256 + 3'd1;
		else
		wr_cycle_cnt_6p_1256 <= wr_cycle_cnt_6p_1256; 
 end
end



reg [2:0] wr_cycle_cnt_6p_34;                 //wr_cycle_cnt for 34 port of 6port case
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
 wr_cycle_cnt_6p_34 <= 3'd0;
 else begin
   if (in_srart)
   wr_cycle_cnt_6p_34 <= 3'd0;
   else if (port_num_6 & (cycle_1 | cycle_2 | cycle_4 | cycle_5))
        wr_cycle_cnt_6p_34 <= wr_cycle_cnt_6p_34 + 3'd1;
		else
		wr_cycle_cnt_6p_34 <= wr_cycle_cnt_6p_34;
 end
end



reg [2:0] wr_cycle_cnt_4n;                 //wr_cycle_cnt for 4n port case
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
 wr_cycle_cnt <= 3'd0;
 else begin
   if (in_srart)
   wr_cycle_cnt_4n <= 3'd0;
   else if (port_num_4n & cycle_3)
   wr_cycle_cnt_4n <= wr_cycle_cnt_4n + 3'd1;
        else
		wr_cycle_cnt_4n <= wr_cycle_cnt_4n; 
 end
end




wire [2:0] wr_cycle_cnt = (port_num_6 & port_1256) ? wr_cycle_cnt_6p_1256 : ((port_num_6 & port_34) ? wr_cycle_cnt_6p_34 : wr_cycle_cnt_4n);





// data in shift reg    p.s. 8/10 bit out bypass shift reg

reg [143:0] sft_reg;
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
 sft_reg <= 144'd0;
 else begin
   if (final_pasel) begin   //2pair
    case(opbit) 
      2'd0: // 6 bits
      begin
        case(wr_cycle_cnt)
		  // 6port case
          3'b000:
            sft_reg[143:138] <= in_r[9:4];
			sft_reg[135:130] <= in_g[9:4];
			sft_reg[137:136] <= in_b[9:8];
			sft_reg[127:124] <= in_b[7:4];
			
          3'b001:
            sft_reg[129:128] <= in_r[9:8];
			sft_reg[119:116] <= in_r[7:4];
            sft_reg[123:120] <= in_g[9:6];
			sft_reg[111:110] <= in_g[5:4];
            sft_reg[115:112] <= in_b[9:6];
            sft_reg[103:102] <= in_b[5:4];
            
          3'b010:
            sft_reg[109:104] <= in_r[9:4];
			sft_reg[101:96]  <= in_g[9:4];
			sft_reg[95:90]   <= in_b[9:4];
			
          3'b011:
            sft_reg[87:82]   <= in_r[9:4];
			sft_reg[89:88]   <= in_g[9:8];
			sft_reg[79:76]   <= in_g[7:4];
			sft_reg[81:80]   <= in_b[9:8];
			sft_reg[71:68]   <= in_b[7:4];
			
          3'b100:
		    sft_reg[75:72]   <= in_r[9:6];
		    sft_reg[63:62]   <= in_r[5:4];
		    sft_reg[67:64]   <= in_g[9:6];
		    sft_reg[55:53]   <= in_g[5:4];
		    sft_reg[61:56]   <= in_b[9:4];
			
		  3'b101:
		    sft_reg[53:48]   <= in_r[9:4];
		    sft_reg[47:42]   <= in_g[9:4];
		    sft_reg[39:34]   <= in_b[9:4];
		   
          3'b110:
		    sft_reg[41:40]   <= in_r[9:8];
		    sft_reg[31:28]   <= in_r[7:4];
		    sft_reg[33:32]   <= in_g[9:8];
		    sft_reg[23:20]   <= in_g[7:4];
		    sft_reg[27:24]   <= in_b[9:6];
		    sft_reg[15:14]   <= in_b[5:4];
		    		   
          3'b111:
		    sft_reg[19:16]   <= in_r[9:6];
			sft_reg[7:6]     <= in_r[5:4];
		    sft_reg[13:8]    <= in_g[9:4];
		    sft_reg[5:0]     <= in_b[9:4];
        endcase
      end
      default: // 8/10 bits
      sft_reg <= 143'd0;
    endcase
   end	
   else begin  //1pair
   case(opbit) 
     2'd0: // 6 bits
     begin
       case(wr_cycle_cnt)  
	     // 6port case
         3'b000:
          sft_reg[143:138] <= in_r[9:4];
   		  sft_reg[137:132] <= in_g[9:4];
   		  sft_reg[131:126] <= in_b[9:4];
   		
         3'b001:
           sft_reg[125:120] <= in_r[9:4];
           sft_reg[119:114] <= in_g[9:4];
           sft_reg[113:108] <= in_b[9:4];
           
         3'b010:
           sft_reg[107:102] <= in_r[9:4];
   		   sft_reg[101:96]  <= in_g[9:4];
   		   sft_reg[95:90]   <= in_b[9:4];
   		
         3'b011:
           sft_reg[89:84]   <= in_r[9:4];
   		   sft_reg[83:78]   <= in_g[9:4];
   		   sft_reg[77:72]   <= in_b[9:4];
		   
   		 3'b100:
		    sft_reg[71:66]   <= in_r[9:4];
		    sft_reg[65:60]   <= in_g[9:4];
		    sft_reg[59:54]   <= in_b[9:4];
			
		 3'b101:
		    sft_reg[53:48]   <= in_r[9:4];
		    sft_reg[47:42]   <= in_g[9:4];
		    sft_reg[41:36]   <= in_b[9:4];
		   
         3'b110:
		    sft_reg[35:30]   <= in_r[9:4];
		    sft_reg[29:24]   <= in_g[9:4];
		    sft_reg[23:18]   <= in_b[9:4];
		  
         3'b111:
		    sft_reg[17:12]   <= in_r[9:4];
		    sft_reg[11:6]    <= in_g[9:4];
		    sft_reg[5:0]     <= in_b[9:4];
        endcase
      end
      default: // 8/10 bits
      sft_reg <= 143'd0;
    endcase
   end
  end
 end

 





 
 
 
 
 
 
 
 
 
 
 
 

///////////////////////////////////////////////
//                                           //
//         pack out cnt Pre-process          //
//                                           //
///////////////////////////////////////////////

//packer counter start
reg in_srart_d1, in_srart_d2;
wire in_srart_extend = in_srart | in_srart_d1 | in_srart_d2;  //for 6port case

always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
 begin
  in_srart_d1 <= 1'd0; 
  in_srart_d2 <= 1'd0; 
 end else begin
     in_srart_d1 <= in_srart; 
     in_srart_d2 <= in_srart_d1; 
     end
end



reg [1:0] cycle_2_cnt;                                    //for 4n_port pack_cnt_start flag       
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
 cycle_2_cnt <= 2'd0;
 else begin
  if (in_srart)
  cycle_2_cnt <= 2'd0;
  else if (cycle_2_cnt == 2'd3)
       cycle_2_cnt <= 2'd3
       else if (in_cycle_cnt == 3'd2)
            cycle_2_cnt <= cycle_2_cnt + 2'd1;
			else
			cycle_2_cnt <= cycle_2_cnt;
 end
end

reg pack_cnt_start;
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
  pack_cnt_start <= 1'd0;
 else begin 
  if (port_num_6)
  pack_cnt_start <= (in_cycle_cnt == 3'd1) & in_srart_extend;
  else if (cycle_2_cnt == 2'd2)
       pack_cnt_start <= 1'd1;
	   else
	   pack_cnt_start <= 1'd0; 
 end
end


















///////////////////////////////////////////////
//                                           //
//             pack out counter              //
//                                           //
///////////////////////////////////////////////

reg [3:0] pack_cnt_temp;              //only for 6port case
reg [3:0] pack_cnt_temp_end;

always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
  pack_cnt_temp <= 4'd0;
 else begin 
   if (port_num_4n)
   pack_cnt_temp <= 4'd0;
   else if (pack_cnt_start)
        pack_cnt_temp <= 4'd0;
        else if (pack_cnt_temp == pack_cnt_temp_end)
		     pack_cnt_temp <= 4'd0;
			 else
			 pack_cnt_temp <= pack_cnt_temp + 4'd1;
 end
end


always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
  pack_cnt_temp_end <= 4'd0;
 else begin
   if (port_num_4n)
   pack_cnt_temp_end <= 4'd0;
   else if (port_num_6)
        pack_cnt_temp_end <= 4'd11;
		else
		pack_cnt_temp_end <= 4'd0; 
  end
 end

 
 
// fpr 6port 6bit packer add flag
wire pack_cnt_temp_0 = (pack_cnt_temp == 4'd0) ? 1'd1: 1'd0;
wire pack_cnt_temp_1 = (pack_cnt_temp == 4'd1) ? 1'd1: 1'd0;
wire pack_cnt_temp_2 = (pack_cnt_temp == 4'd2) ? 1'd1: 1'd0;
wire pack_cnt_temp_3 = (pack_cnt_temp == 4'd3) ? 1'd1: 1'd0;
wire pack_cnt_temp_4 = (pack_cnt_temp == 4'd4) ? 1'd1: 1'd0;
wire pack_cnt_temp_5 = (pack_cnt_temp == 4'd5) ? 1'd1: 1'd0;
wire pack_cnt_temp_6 = (pack_cnt_temp == 4'd6) ? 1'd1: 1'd0;
wire pack_cnt_temp_7 = (pack_cnt_temp == 4'd7) ? 1'd1: 1'd0;
wire pack_cnt_temp_8 = (pack_cnt_temp == 4'd8) ? 1'd1: 1'd0;
wire pack_cnt_temp_9 = (pack_cnt_temp == 4'd9) ? 1'd1: 1'd0;
wire pack_cnt_temp_10 = (pack_cnt_temp == 4'd10) ? 1'd1: 1'd0;
wire pack_cnt_temp_11 = (pack_cnt_temp == 4'd11) ? 1'd1: 1'd0;

wire pack_cnt_add_1256 = pack_cnt_temp_0 | pack_cnt_temp_3 | pack_cnt_temp_5 | pack_cnt_temp_6 | pack_cnt_temp_8 | pack_cnt_temp_11;
wire pack_cnt_add_34   = pack_cnt_temp_1 | pack_cnt_temp_4 | pack_cnt_temp_5 | pack_cnt_temp_7 | pack_cnt_temp_8 | pack_cnt_temp_11;
 
 
 
 
 
 
// 6port 6bit packer counter 
reg [2:0] pack_cnt_6p;                       
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
  pack_cnt_6p <= 3'd0;
 else begin
   if (port_num_4n)
   pack_cnt_6p <= 3'd0;
   else if (pack_cnt_start)
        pack_cnt_6p <= 3'd0;
		else if (pack_cnt_6p == 3'd5)
		     pack_cnt_6p <= 3'd0;
             else if (port_1256 & pack_cnt_add_1256)
                  pack_cnt_6p <= pack_cnt_6p + 3'd1;
	           	  else if (port_34 & pack_cnt_add_34)
                       pack_cnt_6p <= pack_cnt_6p + 3'd1;
	           	       else 
	           	       pack_cnt_6p <= pack_cnt_6p;
  end
end 
 
 

 
// 4n port 6bit packer counter 
reg [2:0] pack_cnt_4n; 
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
  pack_cnt_4n <= 3'd0;
 else begin
   if (port_num_6)
   pack_cnt_4n <= 3'd0;
   else if (pack_cnt_start)
        pack_cnt_4n <= 3'd0;
		else if (pack_cnt_4n == 3'd7)
		     pack_cnt_4n <= 3'd0;
			 else if (in_cycle_cnt == 3'd3)
			 pack_cnt_4n <= pack_cnt_4n + 3'd1;
			      else
				  pack_cnt_4n <= pack_cnt_4n; 
 end
end 
 
 


 
//packer counter 
wire [2:0] pack_cnt = port_num_4n ? pack_cnt_4n : pack_cnt_6p;















///////////////////////////////////////////////
//                                           //
//   read out package data from shift reg    //
//                                           //
///////////////////////////////////////////////



// package out enable flag

reg packout_flag_16p;
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
  packout_flag_16p <= 1'd0;
 else begin
  if (pack_cnt_start)
  packout_flag_16p <= 1'd1;
  else if (in_cycle_cnt == 3'd3)
       packout_flag_16p <= 1'd1;
	   else
       packout_flag_16p <= 1'd0;
 end
end 

wire packout_en_16p = de_d5 & packout_flag_16p;




reg packout_flag_12p;
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
  packout_flag_12p <= 1'd0;
 else begin
  if (pack_cnt_start)
  packout_flag_12p <= 1'd1;
  else if (in_cycle_cnt == 3'd2)
       packout_flag_12p <= 1'd1;
	   else
       packout_flag_12p <= 1'd0;
 end
end 

wire packout_en_12p = de_d4 & packout_flag_12p;

 


reg packout_flag_8p;
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
  packout_flag_8p <= 1'd0;
 else begin
  if (pack_cnt_start)
  packout_flag_8p <= 1'd1;
  else if (in_cycle_cnt == 3'd2)
       packout_flag_8p <= 1'd1;
	   else
       packout_flag_8p <= 1'd0;
 end
end 

wire packout_en_8p = de_d3 & packout_flag_8p; 




reg packout_flag_4p;
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
  packout_flag_4p <= 1'd0;
 else begin
  if (pack_cnt_start)
  packout_flag_4p <= 1'd1;
  else if (in_cycle_cnt == 3'd2)
       packout_flag_4p <= 1'd1;
	   else
       packout_flag_4p <= 1'd0;
 end
end 

wire packout_en_4p = de_d2 & packout_flag_4p;  




reg packout_flag_6p_1256;
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
  packout_flag_6p_1256 <= 1'd0;
 else begin
  if (pack_cnt_start)
  packout_flag_6p_1256 <= 1'd1;
  else if (pack_cnt_add_1256)
       packout_flag_6p_1256 <= 1'd1;
	   else
	   packout_flag_6p_1256 <= 1'd0; 
 end
end

wire packout_en_6p_1256 = de_d4 & packout_flag_6p_1256





reg packout_flag_6p_34;
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
  packout_flag_6p_34 <= 1'd0;
 else begin
  if (pack_cnt_start)
  packout_flag_6p_34 <= 1'd1;
  else if (pack_cnt_add_34)
       packout_flag_6p_34 <= 1'd1;
	   else
	   packout_flag_6p_34 <= 1'd0; 
 end
end
 
wire packout_en_6p_34 = de_d4 & packout_flag_6p_34

 
 

// packout_en
wire packout_en = port_num_16 ? packout_en_16p : ((port_num_12 ? packout_en_12p : (port_num_8 ? packout_en_8p : (port_num_4 ? packout_en_4p : ((port_num_6 & port_1256) ? packout_en_6p_1256 : ((port_num_6 & port_34) ? packout_en_6p_34 : 1'd0))))));





 
// package data out from shift reg
reg [23:0] sr_dout;
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
  packout_flag_6p_34 <= 24'd0;
 else begin
   if (packout_en) begin
   case (port_num_6, pack_cnt)
    //4n port case
    4'b0000: sr_dout <= sft_reg[143:120];
    4'b0001: sr_dout <= sft_reg[119:96];
	4'b0010: sr_dout <= sr_dout;
	4'b0011: sr_dout <= sft_reg[95:72];
	4'b0100: sr_dout <= sft_reg[71:48];
	4'b0101: sr_dout <= sft_reg[47:24];
	4'b0110: sr_dout <= sft_reg[23:0];
	4'b0111: sr_dout <= sr_dout;
	//6 port case
	4'b0000: sr_dout <= sft_reg[143:120];
    4'b0001: sr_dout <= sft_reg[119:96];
	4'b0010: sr_dout <= sft_reg[95:72];
	4'b0011: sr_dout <= sft_reg[71:48];
	4'b0100: sr_dout <= sft_reg[47:24];
	4'b0101: sr_dout <= sft_reg[23:0];
    default: sr_dout <= sr_dout;
   endcase
   end else
   sr_dout <= sr_dout;
 end
end
 



reg [23:0] dout;
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
  dout <= 24'd0;
 else begin
  if (port_num_6 ) 



 

 end
end















endmodule




























